package com.xnck.ifpms.service;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import org.nutz.dao.Cnd;
import org.nutz.dao.sql.Criteria;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.xnck.ifpms.dao.ActionDao;
import com.xnck.ifpms.dao.ActionResourceDao;
import com.xnck.ifpms.dao.ResourceDao;
import com.xnck.ifpms.dao.RoleActionDao;
import com.xnck.ifpms.dao.RoleDao;
import com.xnck.ifpms.entity.Action;
import com.xnck.ifpms.entity.ActionResource;
import com.xnck.ifpms.entity.Resource;
import com.xnck.ifpms.entity.Role;
import com.xnck.ifpms.entity.RoleAction;
import com.xnck.ifpms.model.TreeNode;
import com.xiaoleilu.hutool.DateUtil;
import com.xiaoleilu.hutool.StrUtil;

/**
 * 权限业务逻辑
 * @author zhangmengliang
 *
 */
@Service
public class ActionService {

	@Autowired
	private ActionDao actionDao;
	
	@Autowired
	private RoleDao roleDao;
	
	@Autowired
	private RoleActionDao roleActionDao;
	
	@Autowired
	private ResourceDao resourceDao;
	
	@Autowired
	private ActionResourceDao actionResourceDao;
	
	/**
	 * 根据条件获得权限的总数量
	 * @param actionName 权限名称(可为NULL)
	 * @param remark 备注(可为NULL)
	 * @return
	 * @author:zhangmengliang
	 * @date: 2015年10月25日
	 */
	public Integer getActionsCount(String actionName, String remark){
		Criteria cri = Cnd.cri();
		if (StrUtil.isNotBlank(actionName)) {
			cri.where().andLike(Action.FIELD_DISPLAYNAME, "%" + actionName + "%");
		}
		if (StrUtil.isNotBlank(remark)) {
			cri.where().andLike(Action.FIELD_REMARK, "%" + remark + "%");
		}
		return actionDao.searchCount(cri);
	}
	
	/**
	 * 根据条件分页获得权限集合
	 * @param parentId 父级ID(可为NULL)
	 * @param actionName 权限名称(可为NULL)
	 * @param remark 备注(可为NULL)
	 * @param currentPage 当前页码
	 * @param pageSize 页大小
	 * @return
	 * @author:zhangmengliang
	 * @date: 2015年10月25日
	 */
	public List<Action> getActions(String parentId, String actionName, String remark, Integer currentPage,Integer pageSize){
		if (null == currentPage || null == pageSize) {
			currentPage = 0;
			pageSize = 20;
		}
		Criteria cri = Cnd.cri();
		if (StrUtil.isNotBlank(parentId)) {
			cri.where().and(Action.FIELD_PARENTID, "=", parentId);
		}
		if (StrUtil.isNotBlank(actionName)) {
			cri.where().andLike(Action.FIELD_DISPLAYNAME, "%" + actionName + "%");
		}
		if (StrUtil.isNotBlank(remark)) {
			cri.where().andLike(Action.FIELD_REMARK, "%" + remark + "%");
		}
		cri.getOrderBy().desc(Action.FIELD_ADDTIME);
		return actionDao.searchByPage(cri, currentPage, pageSize);
	}
	
	/**
	 * 根据ID获得权限
	 * @param id 主键ID
	 * @return
	 * @author:zhangmengliang
	 * @date: 2015年10月25日
	 */
	public Action getAction(String id){
		return actionDao.get(id);
	}
	
	/**
	 * 根据父级ID获得一级子权限集合
	 * @param parentId 父级ID
	 * @return
	 * @author:zhangmengliang
	 * @date: 2015年10月25日
	 */
	public List<TreeNode> getActionNodesByParentId(String parentId){
		List<Action> actions = actionDao.search(Cnd.where(Action.FIELD_PARENTID, "=", parentId));
		List<TreeNode> treeNodes = new ArrayList<TreeNode>();
		for (Action action : actions) {
			TreeNode treeNode = new TreeNode();
			treeNode.setId(action.getId());
			if (null != action.getChildcount() && action.getChildcount() > 0) {
				treeNode.setIsParent(true);
			}
			else {
				treeNode.setIsParent(false);
			}
			treeNode.setName(action.getDisplayname());
			treeNodes.add(treeNode);
		}
		return treeNodes;
	}
	
	/**
	 * 保存权限信息
	 * @param id 主键标识(可为NULL,为NULL时创建否则修改)
	 * @param parentId 父级ID
	 * @param actionName 权限名称
	 * @param remark 备注
	 * @param enable 是否可用
	 * @param curUserId 操作者
	 * @return 新创建或更新后的权限信息
	 * @author:zhangmengliang
	 * @date: 2015年10月25日
	 */
	public Action saveAction(String id, String parentId, String actionName, String remark, Boolean enable, String curUserId){
		Action action = null;
		if (StrUtil.isNotBlank(id)) {
			action = actionDao.get(id);
		}
		if (null == action) {
			return this.insertAction(parentId, actionName, remark, enable, curUserId);
		}
		else {
			int childCount = actionDao.searchCount(Cnd.where(Action.FIELD_PARENTID, "=", id));
			Boolean isParent = false;
			if (childCount > 0) {
				isParent = true;
			}
			return this.updateAction(action, parentId, isParent, actionName, remark, enable);
		}
	}
	
	/**
	 * 新增权限
	 * @param parentId 父级ID
	 * @param actionName 权限名称
	 * @param remark 备注
	 * @param enable 是否可用
	 * @param curUserId 操作者
	 * @return
	 * @author:zhangmengliang
	 * @date: 2015年10月25日
	 */
	private Action insertAction(String parentId, String actionName, String remark, Boolean enable, String curUserId){
		Action action = new Action();
		action.setId(UUID.randomUUID().toString());
		action.setParentid(parentId);
		action.setDisplayname(actionName);
		action.setRemark(remark);
		action.setEnable(enable);
		action.setAddtime(DateUtil.date());
		action.setCreaterid(curUserId);
		return actionDao.insert(action);
	}
	
	/**
	 * 更新权限
	 * @param action 旧的权限信息
	 * @param parentId 新的父级ID
	 * @param isParent 是否是父级
	 * @param actionName 新的权限名称
	 * @param remark 新的备注信息
	 * @param enable 是否可用
	 * @return
	 * @author:zhangmengliang
	 * @date: 2015年10月25日
	 */
	private Action updateAction(Action action, String parentId, Boolean isParent, String actionName, String remark, Boolean enable){
		action.setParentid(parentId);
		action.setDisplayname(actionName);
		action.setRemark(remark);
		action.setEnable(enable);
		actionDao.update(action);
		return action;
	}
	
	/**
	 * 根据ID删除权限信息
	 * @param id 主键标识
	 * @author:zhangmengliang
	 * @date: 2015年10月25日
	 */
	public void delAction(String id){
		actionDao.delete(id);
	}
	
	/**
	 * 根据以","隔开的ID字符串删除权限信息
	 * @param ids 以","隔开的ID
	 * @author:zhangmengliang
	 * @date: 2015年10月25日
	 */
	public void delActions(String ids){
		Criteria cri = Cnd.cri();
		cri.where().andIn(Action.FIELD_ID, ids.split(","));
		actionDao.clear(cri);
	}
	
	/**
	 * 根据条件获得权限所关联的角色信息数量
	 * @param actionId 权限ID
	 * @param roleName 角色名称(可为NULL)
	 * @return
	 * @author:zhangmengliang
	 * @date: 2015年10月25日
	 */
	public Integer getCountRoleForAction(String actionId, String roleName){
		Criteria cri = Cnd.cri();
		if (StrUtil.isNotBlank(roleName)) {
			cri.where().andLike(Role.FIELD_DISPLAYNAME, roleName);
		}
		return roleDao.getCountRolesForAction(actionId, cri);
	}
	
	/**
	 * 根据条件分页获得权限所关联的角色，以DisplayName倒序
	 * @param actionId 权限ID
	 * @param roleName 角色名称(可为NULL)
	 * @param currentPage 当前页码
	 * @param pageSize 页大小
	 * @return
	 * @author:zhangmengliang
	 * @date: 2015年10月25日
	 */
	public List<Role> getRoleForAction(String actionId, String roleName, Integer currentPage,Integer pageSize){
		if (null == currentPage || null == pageSize) {
			currentPage = 0;
			pageSize = 20;
		}
		Criteria cri = Cnd.cri();
		if (StrUtil.isNotBlank(roleName)) {
			cri.where().andLike(Role.FIELD_DISPLAYNAME, roleName);
		}
		cri.getOrderBy().desc(Role.FIELD_DISPLAYNAME);
		return roleDao.getRolesForAction(actionId, cri, currentPage, pageSize);
	}
	
	/**
	 * 根据条件获得权限未关联的角色数量
	 * @param actionId 权限ID
	 * @param roleName 角色名称(可为NULL)
	 * @return
	 * @author:zhangmengliang
	 * @date: 2015年10月25日
	 */
	public Integer getCountRoleNotForAction(String actionId, String roleName){
		Criteria cri = Cnd.cri();
		if (StrUtil.isNotBlank(roleName)) {
			cri.where().andLike(Role.FIELD_DISPLAYNAME, roleName);
		}
		return roleDao.getCountRolesNotForAction(actionId, cri);
	}
	
	/**
	 * 根据条件分页获得权限未关联的角色信息,以DisplayName倒序
	 * @param actionId 权限ID
	 * @param roleName 角色名称(可为NULL)
	 * @param currentPage 当前页码
	 * @param pageSize 页大小
	 * @return
	 * @author:zhangmengliang
	 * @date: 2015年10月25日
	 */
	public List<Role> getRoleNotForAction(String actionId, String roleName, Integer currentPage,Integer pageSize){
		if (null == currentPage || null == pageSize) {
			currentPage = 0;
			pageSize = 20;
		}
		Criteria cri = Cnd.cri();
		if (StrUtil.isNotBlank(roleName)) {
			cri.where().andLike(Role.FIELD_DISPLAYNAME, roleName);
		}
		cri.getOrderBy().desc(Role.FIELD_DISPLAYNAME);
		return roleDao.getRolesNotForAction(actionId, cri, currentPage, pageSize);
	}
	
	/**
	 * 关联权限和角色
	 * @param actionId 权限ID
	 * @param roleIds 以","分隔的角色ID字符串
	 * @author:zhangmengliang
	 * @date: 2015年10月25日
	 */
	public void setActionRoles(String actionId, String roleIds){
		if (StrUtil.isBlank(actionId) || StrUtil.isBlank(roleIds)) {
			return;
		}
		Criteria cri = Cnd.cri();
		cri.where().andIn(Role.FIELD_ID, roleIds.split(","));
		List<Role> roles = roleDao.search(cri);
		Action action = actionDao.get(actionId);
		if (null == action || roles.size() == 0) {
			return;
		}
		action.setRoles(roles);
		actionDao.insertRelation(action, Action.FIELD_ROLES);
	}
	
	/**
	 * 移除权限和角色的关联关系
	 * @param actionId 权限ID
	 * @param roleIds 以","分隔的角色ID字符串
	 * @author:zhangmengliang
	 * @date: 2015年10月25日
	 */
	public void removeActionRoles(String actionId, String roleIds){
		if (StrUtil.isBlank(actionId) || StrUtil.isBlank(roleIds)) {
			return;
		}
		Criteria cri = Cnd.cri();
		cri.where().and(RoleAction.FIELD_ACTIONID, "=", actionId).andIn(RoleAction.FIELD_ROLEID, roleIds.split(","));
		roleActionDao.clear(cri);
	}
	
	/**
	 * 获得权限所具有的资源数量
	 * @param actionId 权限ID
	 * @param resourceName 资源名称(可为NULL)
	 * @return
	 * @author:zhangmengliang
	 * @date: 2015年10月25日
	 */
	public Integer getCountResourceForAction(String actionId, String resourceName){
		Criteria cri = Cnd.cri();
		if (StrUtil.isNotBlank(resourceName)) {
			cri.where().andLike(Resource.FIELD_DISPLAYNAME, resourceName);
		}
		return resourceDao.getCountResourcesForAction(actionId, cri);
	}
	
	/**
	 * 分页获得权限所具有的资源，以DisplayName倒序
	 * @param actionId 权限ID
	 * @param resourceName 资源名称(可为NULL)
	 * @param currentPage 当前页码
	 * @param pageSize 页大小
	 * @return
	 * @author:zhangmengliang
	 * @date: 2015年10月25日
	 */
	public List<Resource> getResourceForAction(String actionId, String resourceName, Integer currentPage,Integer pageSize){
		if (null == currentPage || null == pageSize) {
			currentPage = 0;
			pageSize = 20;
		}
		Criteria cri = Cnd.cri();
		if (StrUtil.isNotBlank(resourceName)) {
			cri.where().andLike(Resource.FIELD_DISPLAYNAME, resourceName);
		}
		cri.getOrderBy().desc(Resource.FIELD_DISPLAYNAME);
		return resourceDao.getResourcesForAction(actionId, cri, currentPage, pageSize);
	}
	
	/**
	 * 获得权限所不具有的资源数量
	 * @param actionId 权限ID
	 * @param resourceName 资源名称(可为NULL)
	 * @return
	 * @author:zhangmengliang
	 * @date: 2015年10月25日
	 */
	public Integer getCountResourceNotForAction(String actionId, String resourceName){
		Criteria cri = Cnd.cri();
		if (StrUtil.isNotBlank(resourceName)) {
			cri.where().andLike(Resource.FIELD_DISPLAYNAME, resourceName);
		}
		return resourceDao.getCountResourcesNotForAction(actionId, cri);
	}
	
	/**
	 * 分页获得权限所不具有的资源,以DisplayName倒序
	 * @param actionId 权限ID
	 * @param resourceName 资源名称(可为NULL)
	 * @param currentPage 当前页码
	 * @param pageSize 页大小
	 * @return
	 * @author:zhangmengliang
	 * @date: 2015年10月25日
	 */
	public List<Resource> getResourceNotForAction(String actionId, String resourceName, Integer currentPage,Integer pageSize){
		if (null == currentPage || null == pageSize) {
			currentPage = 0;
			pageSize = 20;
		}
		Criteria cri = Cnd.cri();
		if (StrUtil.isNotBlank(resourceName)) {
			cri.where().andLike(Resource.FIELD_DISPLAYNAME, resourceName);
		}
		cri.getOrderBy().desc(Resource.FIELD_DISPLAYNAME);
		return resourceDao.getResourcesNotForAction(actionId, cri, currentPage, pageSize);
	}
	
	/**
	 * 关联权限和资源
	 * @param actionId 权限ID
	 * @param resourceIds 以","分隔的权限ID字符串
	 * @author:zhangmengliang
	 * @date: 2015年10月25日
	 */
	public void setActionResources(String actionId, String resourceIds){
		if (StrUtil.isBlank(actionId) || StrUtil.isBlank(resourceIds)) {
			return;
		}
		Criteria cri = Cnd.cri();
		cri.where().andIn(Resource.FIELD_ID, resourceIds.split(","));
		List<Resource> resources = resourceDao.search(cri);
		Action action = actionDao.get(actionId);
		if (null == action || resources.size() == 0) {
			return;
		}
		action.setResources(resources);
		actionDao.insertRelation(action, Action.FIELD_RESOURCES);
	}
	
	/**
	 * 移除权限和资源
	 * @param actionId 权限ID
	 * @param resourceIds 以","分隔的权限ID字符串
	 * @author:zhangmengliang
	 * @date: 2015年10月25日
	 */
	public void removeActionResources(String actionId, String resourceIds){
		if (StrUtil.isBlank(actionId) || StrUtil.isBlank(resourceIds)) {
			return;
		}
		Criteria cri = Cnd.cri();
		cri.where().and(ActionResource.FIELD_ACTIONID, "=", actionId).andIn(ActionResource.FIELD_RESOURCEID, resourceIds.split(","));
		actionResourceDao.clear(cri);
	}
}
